package nio;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

import config.Config;

public class FileNetReceiverNIO {
	public static void main(String[] args) throws IOException {
		try (ServerSocketChannel serverSocketChannel = ServerSocketChannel
				.open();) {
			serverSocketChannel.socket().bind(
					new InetSocketAddress(Config.NET_SERVER_IP,
							Config.NET_SERVER_PORT));
			serverSocketChannel.configureBlocking(true);

			while (true) {
				System.out.println("Waiting for connection...");
				try (SocketChannel socketChannel = serverSocketChannel.accept();) {
					System.out.println("Server at: "
							+ socketChannel.getLocalAddress() + ".");
					System.out.println("Received an incoming connection from "
							+ socketChannel.socket().getRemoteSocketAddress()
							+ ".");

					int totalRcvdBytes = 0;
					int size = Integer.MAX_VALUE;

					ByteBuffer buf = ByteBuffer.allocate(Config.NET_BUF_SIZE);

					try (FileOutputStream fileOutputStream = new FileOutputStream(
							new File(Config.OUTPUT_FILE_NET_NIO));
							FileChannel fileChannel = fileOutputStream
									.getChannel()) {

						while (size >= 0
								&& totalRcvdBytes < Config.FILE_SIZE_BYTES) {
							buf.clear();
							size = socketChannel.read(buf);
							totalRcvdBytes += size;
							buf.flip();
							while (buf.hasRemaining()) {
								fileChannel.write(buf);
							}
							if (totalRcvdBytes > 0 && size > 0
									&& totalRcvdBytes == size) {
								System.out
										.printf("First %d bytes received. Receiving more data...\n",
												size);
							}
						}

						ByteBuffer ackBuf = ByteBuffer.allocate(1);
						ackBuf.clear();
						ackBuf.put((byte) Config.TX_ACK_BYTE);
						ackBuf.flip();
						socketChannel.write(ackBuf);
						System.out
								.println("All data is received. TX ack sent.");
					}
				}

				break;
			}
		} catch (IOException e) {
			System.out.println("I/O exception. Details: " + e.getMessage());
			e.printStackTrace();
		}
	}
}
